/*
 *
 */
#include "gkt_debug.h"
#include "gkt_gpio.h"
#include "gkt_os.h"
#include "gkt_ambient_light.h"

#if GKT_AMBIENT_LIGHT_ENABLE \
	&& defined(GKT_CONFIG_AMBIENT_LIGHT_META_COLOR_NUMS) \
	&& (GKT_CONFIG_AMBIENT_LIGHT_META_COLOR_NUMS == 2) \
	&& defined(GKT_CONFIG_AMBIENT_LIGHT_META_GPIO_PIN_NUMS) \
	&& (GKT_CONFIG_AMBIENT_LIGHT_META_GPIO_PIN_NUMS == 1) \
	&& defined(GKT_CONFIG_AMBIENT_LIGHT_META_0_GPIO_PIN)

#if defined(GKT_CONFIG_AMBIENT_LIGHT_FLICKER_ENABLE) \
	&& GKT_CONFIG_AMBIENT_LIGHT_FLICKER_ENABLE
#define AMBIENT_LIGHT_FLICKER_ENABLE	1
#else
#define AMBIENT_LIGHT_FLICKER_ENABLE	0
#endif

/*
 * STATE_OFF(0) - GPIO INPUT
 * STATE_META_LIGHT_0_ON(1) - GPIO OUTPUT - X
 * STATE_META_LIGHT_1_ON(2) - GPIO OUTPUT - !X
 */
enum {
	AMBIENT_LIGHT_STATE_OFF = GKT_AMBIENT_LIGHT_STATE_OFF,
	AMBIENT_LIGHT_STATE_0_ON,
	AMBIENT_LIGHT_STATE_1_ON,
	AMBIENT_LIGHT_STATE_MAX
};

#ifdef GKT_CONFIG_AMBIENT_LIGHT_STATE_0_ON_LEVEL
#define AMBIENT_LIGHT_STATE_0_ON_LEVEL	\
	GKT_CONFIG_AMBIENT_LIGHT_STATE_0_ON_LEVEL
#else
#define AMBIENT_LIGHT_STATE_0_ON_LEVEL	0
#endif
#if AMBIENT_LIGHT_STATE_0_ON_LEVEL
#define AMBIENT_LIGHT_STATE_1_ON_LEVEL	0
#else
#define AMBIENT_LIGHT_STATE_1_ON_LEVEL	1
#endif

typedef struct _ambient_light {
#if AMBIENT_LIGHT_FLICKER_ENABLE
	gkt_mutex_t	mutex;
	gkt_soft_timer_t	flicker_soft_timer;
	int	flicker_soft_timer_start;
	uint32_t	flicker_loops_left;
#endif

	uint32_t	state;
	int	io_output;	/* input: both lights are off, output: one light is on */
	uint32_t	io_level;
} ambient_light_s;
static ambient_light_s s_ambient_light;

static void ambient_light_off(int complete)
{
	if (complete) {
		s_ambient_light.state = GKT_AMBIENT_LIGHT_STATE_OFF;
#if AMBIENT_LIGHT_FLICKER_ENABLE
		if (s_ambient_light.flicker_soft_timer_start) {
			s_ambient_light.flicker_soft_timer_start = 0;
			gkt_soft_timer_stop(s_ambient_light.flicker_soft_timer);
		}
#endif
	}

	s_ambient_light.io_output = 0;
	gkt_gpio_config(GKT_CONFIG_AMBIENT_LIGHT_META_0_GPIO_PIN, GKT_GPIO_F_INPUT, NULL);
}

static void ambient_light_on(void)
{
	if (!s_ambient_light.io_output) {
		s_ambient_light.io_output = 1;
		gkt_gpio_config(GKT_CONFIG_AMBIENT_LIGHT_META_0_GPIO_PIN, GKT_GPIO_F_OUTPUT, NULL);
	}

	gkt_gpio_set_pin_level(GKT_CONFIG_AMBIENT_LIGHT_META_0_GPIO_PIN, 
			s_ambient_light.io_level);
}

#if AMBIENT_LIGHT_FLICKER_ENABLE
static void ambient_light_flicker_timer_callback(void *arguments)
{
	gkt_mutex_lock(s_ambient_light.mutex, GKT_INFINITE);
	if (s_ambient_light.flicker_soft_timer_start) {
		if (s_ambient_light.flicker_loops_left > 0) {
			if (s_ambient_light.io_output)
				ambient_light_off(0);
			else {
				s_ambient_light.flicker_loops_left--;
				ambient_light_on();
			}
		}
		else
			ambient_light_off(1);
	}
	gkt_mutex_unlock(s_ambient_light.mutex);
}

void gkt_ambient_light_set_state(uint32_t state, 
		uint32_t half_cycle_time_ms, uint32_t loops)
{
	int retval;

	if (s_ambient_light.mutex)
		gkt_mutex_lock(s_ambient_light.mutex, GKT_INFINITE);

	if ((AMBIENT_LIGHT_STATE_OFF == state)
		&& (s_ambient_light.state != state))
	{
		ambient_light_off(1);
	}
	else if (state < AMBIENT_LIGHT_STATE_MAX) {
		if (s_ambient_light.state != state) {
			ambient_light_off(1);

			s_ambient_light.io_level = (AMBIENT_LIGHT_STATE_0_ON == state) ?
				AMBIENT_LIGHT_STATE_0_ON_LEVEL : AMBIENT_LIGHT_STATE_1_ON_LEVEL;
			ambient_light_on();

			s_ambient_light.state = state;
		}
		else if (s_ambient_light.flicker_soft_timer_start) {
			s_ambient_light.flicker_soft_timer_start = 0;
			gkt_soft_timer_stop(s_ambient_light.flicker_soft_timer);

			if (!s_ambient_light.io_output) {
				s_ambient_light.io_level = (AMBIENT_LIGHT_STATE_0_ON == state) ?
					AMBIENT_LIGHT_STATE_0_ON_LEVEL : AMBIENT_LIGHT_STATE_1_ON_LEVEL;
				ambient_light_on();
			}
		}

		if ((half_cycle_time_ms > 0) && (loops > 0)
			&& s_ambient_light.flicker_soft_timer) 
		{
			s_ambient_light.flicker_loops_left = loops - 1;
			retval = gkt_soft_timer_start(s_ambient_light.flicker_soft_timer,
							half_cycle_time_ms);
			if (GKT_SUCCESS == retval)
				s_ambient_light.flicker_soft_timer_start = 1;
		}
	}

	if (s_ambient_light.mutex)
		gkt_mutex_unlock(s_ambient_light.mutex);
}

#else
void gkt_ambient_light_set_state(uint32_t state, 
		uint32_t half_cycle_time_ms, uint32_t loops)
{
	gkt_unused(half_cycle_time_ms);
	gkt_unused(loops);

	if (s_ambient_light.state != state) {
		if (AMBIENT_LIGHT_STATE_OFF == state)
			ambient_light_off(1);
		else if (state < AMBIENT_LIGHT_STATE_MAX) {
			s_ambient_light.io_level = (AMBIENT_LIGHT_STATE_0_ON == state) ?
				AMBIENT_LIGHT_STATE_0_ON_LEVEL : AMBIENT_LIGHT_STATE_1_ON_LEVEL;
			ambient_light_on();
			s_ambient_light.state = state;
		}
	}
}
#endif

void gkt_ambient_light_init(void)
{
	ambient_light_off(1);

#if AMBIENT_LIGHT_FLICKER_ENABLE
	s_ambient_light.flicker_soft_timer_start = 0;

	s_ambient_light.mutex = gkt_mutex_create(0);
	if (!s_ambient_light.mutex)
		gkt_error("ambient_light: create mutex failed!\n");

	s_ambient_light.flicker_soft_timer = gkt_soft_timer_create(
			GKT_SOFT_TIMER_PERIODIC,
			ambient_light_flicker_timer_callback, NULL);
	if (!s_ambient_light.flicker_soft_timer)
		gkt_error("ambient_light: create flicker_soft_timer failed!\n");
#endif
}

int gkt_ambient_light_standby(void)
{
	int retval=GKT_SUCCESS;
	
#if (GKT_AMBIENT_LIGHT_ENABLE) && defined(GKT_CONFIG_AMBIENT_LIGHT_META_0_GPIO_PIN)
		//gkt_gpio_set_pin_level(GKT_CONFIG_AMBIENT_LIGHT_META_0_GPIO_PIN, !GKT_CONFIG_AMBIENT_LIGHT_META_0_ON);
		retval = gkt_gpio_config(GKT_CONFIG_AMBIENT_LIGHT_META_0_GPIO_PIN,
						GKT_GPIO_F_INPUT|GKT_GPIO_F_INPUT_PULL_DOWN, NULL);
		if (retval != GKT_SUCCESS)
			gkt_error("ambient_light: config meta_0 gpio failed(%d)!\n", retval);
#endif
	return retval;
}

#endif

